home *** CD-ROM | disk | FTP | other *** search
- ; Code from Pascal column in Micro Cornucopia Issue #39
- ;
- ; SCAN.ASM
- ;
- ;
- ; Document scanner resident data capture software.
- ; This software intercepts the real time clock interrupt
- ; with a high speed data capture routine and also installs
- ; a routine at interrupt vector 60H to provide scanning
- ; functions to other programs.
- ;
- ; Since this software incorporates itself into the real time
- ; clock processing, it has the potential of interfering with
- ; other resident software. It is highly recommended that
- ; the absolute minimum of other resident software be installed.
- ;
- ; The software does NOT check for previous use of INT 60H.
- ;
- ; Written for Eric Isaacson's A86 assembler.
- ;
- ; CONST
- ; joystick = 201H;
- ; tickconst = 1024;
- ;
- joystick equ 201h
- tickconst equ 1024
- ;
- code segment ; both code and data in same segment
- ;
- jmp init
- ;
- ; VAR
- ; count : CARDINAL;
- ; counter : CARDINAL;
- ; rasterPtr : POINTER TO raster;
- ; scaning : BOOLEAN;
- ; dosclk : ADDRESS;
- ; tickcount : BYTE;
- ; tickinc : BYTE;
- ;
- count dw ?
- counter dw ?
- ;
- raster_ofs dw
- rasterPtr dd ? ; double word for far data
- scanning db 0 ; FALSE
- ;
- dosclk_ip dw
- dosclk dd ? ; double word for far calls
- ;
- tickcount dw ? ; how many counter cycles?
- tickinc dw tickconst ; fast clock divisor default value
- ;
- ; Restore/Set hardware clock chip
- ;
- restore_clock: xor ax,ax ; normal time constant = 0
- setclk: push ax
- mov al,36h ; control register
- out 43h,al
- pop ax
- out 40h,al ; count low byte
- xchg ah,al
- out 40h,al ; and high byte
- ret
- ;
- ; New clock routine, includes data capture from scanner
- ;
- fastclock: push ax ; interrupt routine, save registers
- push ds
- push es
- push cs ; make ds = cs
- pop ds
- ;
- mov al,scanning ; are we scanning?
- or al,al
- jz notscanning ; if z, no
- ;
- push bx ; scanning, save additional regs
- push cx
- push dx
- ;
- mov bx,raster_ofs ; data address offset
- mov ax,raster_ofs+2 ; and segment previously set
- mov es,ax ; when scan initiated.
- ;
- mov dx,joystick ; input data address
- in al,dx ; get the data
- mov cl,4 ; then shift to low order nybble
- ror al,cl
- and al,0fh
- ;
- push si
- mov si,counter
- es mov b [bx+si],al ; store the data where M2 needs it
- pop si
- inc w counter ; bump the count
- mov ax,count ; done yet?
- cmp ax,counter
- jnz notdone ; not done yet
- ;
- xor al,al ; done, flip flag
- mov scanning,al
- call restore_clock ; reset hardware
- mov tickcount,0 ; ready for next time
- pop dx
- pop cx
- pop bx
- jmp clkexit
- ;
- notdone: pop dx
- pop cx
- pop bx
- ;
- mov ax,tickcount
- add ax,tickinc ; bump tick counter
- mov tickcount,ax
- jnc clkexit ; if no overflow, not time for DOS
- ;
- notscanning:pushf ; simulate software interrupt
- call dosclk ; with pushf and far call
- jmp clkxit2 ; skip eoi to 8259 since dos does it
- ;
- clkexit: mov al,20h ; end of interrupt command
- out 20h,al ; to 8259 interrupt controller
- clkxit2: pop es ; restore registers
- pop ds
- pop ax
- iret
-
- ;
- ; Modula-2 activates the functions in this resident
- ; software with an int 60H instruction. The parameters
- ; needed are passed in the registers AL, BX, CX, and DX.
- ; AL = function #
- ; BX = data (raster) offset
- ; DX = data segment
- ; CX = number of data points to capture or time constant
- ;
- ; The functions currently supported are:
- ; 0 : report address of 'scanning' flag byte (DX:BX)
- ; 1 : restore original clock routine
- ; 2 : capture a scan line of data
- ; 3 : set fast clock speed
- ;
- dispatch: ; M2 call has saved all regs
- or al,al ; report flag address?
- jz rprt_addr
- ;
- cmp al,1 ; restore clock to normal?
- jz killfast
- ;
- cmp al,2 ; get data
- jz capture
- ;
- cmp al,3 ; set fast clock divisor
- jz setfast
- ;
- iret ; unrecognized function, ignore
- ;
- rprt_addr: push ds
- push cs ; data in code segment
- pop dx ; segment address
- mov bx, offset scanning ; and offset
- pop ds ; that's all it takes
- iret
- ;
- setfast: push ds ; set fast clock divisor
- push cs
- pop ds
- mov tickinc,cx ; simple isn't it?
- pop ds
- iret
- ;
- killfast: push ds
- push cs
- pop ds
- call restore_clock ; reset hardware
- mov dx,dosclk_ip ; old offset value
- mov ds,dosclk_ip+2 ; and old segment
- mov ah,25h
- mov al,8
- sti ; can we do an int if disabled?
- int 21h
- pop ds
- iret
- ;
- ; Capture a line of data by setting scanning to TRUE
- ; and activating the fast clock.
- ;
- capture: push ds
- push cs
- pop ds
- mov counter,0 ; data point counter
- mov count,cx ; # points to capture
- mov raster_ofs,bx ; data destination offset
- mov raster_ofs+2,dx ; and segment
- mov scanning,0ffh ; set scanning to TRUE
- ;
- ;
- mov ax,tickinc ; set clock to fast rate
- call setclk
- mov tickcount,0 ; reset tick counter
- pop ds ; return to M2
- iret
- ;
- ;
- ; Install function dispatch routine
- ;
- init: mov ah,25h ; install interrupt function
- mov al,60H ; can only use 60 - 67
- mov dx, offset dispatch
- push cs
- pop ds
- int 21h
- ;
- ; Get and save old clock vector
- ;
- push es
- mov ah,35h ; get vector function
- mov al,8h ; clock vector #
- int 21h
- mov dosclk_ip,bx ; save the long address
- mov dosclk_ip+2,es
- pop es
- ;
- ; Install new clock routine
- ;
- push ds
- mov ah,25h ; install interrupt fxn
- mov al,8h
- mov dx, offset fastclock
- push cs
- pop ds
- int 21h
- pop ds
- ;
- ;
- ; exit to dos, remain resident
- ;
- mov dx,offset init
- int 27h ; terminate but stay resident
- ;
- code ends
- end
-